/* eslint-disable no-use-before-define */
import { Ref } from 'vue'
import { ElTable } from 'element-plus'

/**
 * 用法：
 * const tablePageCheck = new TablePageCheck({...})
 * <el-table @selection-change="tablePageCheck.tableChangeHandle($event)" ...>...</el-table>
 */
type TablePageCheckType = InstanceType<typeof TablePageCheck>
type TablePageCheckConstructorOptions = {
  // el-table 的 data
  tableSource: TablePageCheckType['tableSource']
  // 唯一key，如id
  rowKey: TablePageCheckType['rowKey'],
  // el-table 的 ref实例
  tableRef: TablePageCheckType['tableRef'],
  // 是否自动回显勾选的行
  autoUpdateSelection?: TablePageCheckType['autoUpdateSelection'],
  // 默认勾选的key
  defaultKeys?: Array<any>
  // 默认勾选的行
  defaultRows?: Array<any>
}
export class TablePageCheck {
  tableSource: Ref<Array<any>>
  checkedMap = new Map()
  rowKey: string
  tableRef: Ref<InstanceType<typeof ElTable>>
  autoUpdateSelection = false
  // 是否锁定checkedSet，使其不受change影响赋值
  checkedSetLock = false
  constructor (options: TablePageCheckConstructorOptions) {
    this.tableSource = options.tableSource
    this.rowKey = options.rowKey
    this.tableRef = options.tableRef
    this.autoUpdateSelection = options.autoUpdateSelection || false
    if (options.defaultRows) this.setCheckedRows(options.defaultRows)
    else if (options.defaultKeys) this.setCheckedKeys(options.defaultKeys)
    if (this.autoUpdateSelection) {
      watch(this.tableSource, () => this.updateSelectionRows())
    }
  }

  /**
   * el-table的selection-change实现函数
   * @param e
   */
  tableChangeHandle (e: any[]) {
    if (!this.checkedSetLock) {
      this.tableSource.value.forEach((item) => this.checkedMap.delete(item[this.rowKey]))
      e.forEach((item) => this.checkedMap.set(item[this.rowKey], item))
    }
  }

  /**
   * 获取当前选中的行的keys
   */
  getCheckedKeys () {
    return Array.from<string>(this.checkedMap.keys())
  }

  /**
   * 获取选中的行
   */
  getCheckedRows<T = any[]> () {
    return Array.from<T>(this.checkedMap.values())
  }

  /**
   * 设置当前选中的行的keys
   * @param keys
   * @param render
   */
  setCheckedKeys (keys: Array<string>, render = false) {
    this.checkedMap = new Map()
    for (let i = 0, len = keys.length; i < len; i++) {
      this.checkedMap.set(keys[i], null)
    }
    render && this.updateSelectionRows()
  }

  /**
   * 设置当前选中的行
   * @param rows
   * @param render
   */
  setCheckedRows (rows: Array<any>, render = false) {
    this.checkedMap = new Map()
    for (let i = 0, len = rows.length; i < len; i++) {
      this.checkedMap.set(rows[i][this.rowKey], rows[i])
    }
    render && this.updateSelectionRows()
  }

  /**
   * 更新el-table的选中行
   */
  updateSelectionRows () {
    this.checkedSetLock = true
    requestAnimationFrame(() => {
      const selectionRows = this.tableSource.value.filter(item => this.checkedMap.has(item[this.rowKey]))
      selectionRows.forEach((row) => this.tableRef.value.toggleRowSelection(row, true))
      this.checkedSetLock = false
    })
  }

  /**
   * 清理当前选中的keys
   * @param clearSelection 同时清理el-table的选中状态
   */
  clearCheckedKeys (clearSelection?: boolean) {
    this.checkedMap.clear()
    if (clearSelection) {
      this.tableRef.value.clearSelection()
    }
  }
}
